/**
 * @name 10_dataflow_with_barrier
 * @kind path-problem
 */

import java
import semmle.code.java.dataflow.DataFlow
import DataFlow::PathGraph

predicate isOgnlSink(Expr arg) {
  exists (Method m, MethodAccess ma
  | m.getName() = "compileAndExecute" and
    ma.getMethod() = m and
    arg = ma.getArgument(0))
}

predicate isActionProxySource(MethodAccess ma) {
  exists (Method m, Method n
  | m.getName() = "getNamespace" and
    m.getDeclaringType().getName() = "ActionProxy" and
    n.overrides*(m) and
    ma.getMethod() = n)
}

class OgnlCfg extends DataFlow::Configuration {
  OgnlCfg() { this = "ognl" }

  override predicate isSource(DataFlow::Node source) {
    isActionProxySource(source.asExpr())
  }

  override predicate isSink(DataFlow::Node sink) {
    isOgnlSink(sink.asExpr())
  }

  override predicate isBarrier(DataFlow::Node node) {
    node.getEnclosingCallable().getDeclaringType().getName() = "ValueStackShadowMap"
  }
}

/* If you look at the results of the previous query in the path viewer
 * then you will see that a lot of the results  are not interesting
 * because they go via the class named "ValueStackShadowMap". This class
 * is rarely used in practice, so we want to exclude paths that go
 * through it. In this version of the query, we have overridden
 * `isBarrier` to exclude those paths.
 */
from OgnlCfg cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select source, source, sink, "ognl"
